
#include "PollDispatcher.h"
PollDispatcher::PollDispatcher(EventLoop *eventLoop)
    : Dispatcher(eventLoop)
{
    this->m_maxfd = 0;
    this->m_name = "poll";
    this->m_fds = new struct pollfd[this->m_maxNode];
    for (int i = 0; i < this->m_maxNode; i++)
    {
        this->m_fds[i].fd = -1;
        this->m_fds[i].events = 0;
        this->m_fds[i].revents = 0;
    }
}

int PollDispatcher::add()
{
    // 设置事件events
    int events = 0;
    if (this->m_channel->getEvent()& static_cast<int>(FDEvent::ReadEvent))
    {
        events |= POLLIN;
    }
    // 不能同时判断读或者写
    if (this->m_channel->getEvent() & static_cast<int>(FDEvent::WriteEvent))
    {
        events |= POLLOUT;
    }
    // 遍历找到一个空闲饿、位置放进去

    int i = 0;
    for (; i < this->m_maxNode; i++)
    {
        if (this->m_fds[i].fd == -1)
        {
            // 说明找到一个空闲的位置
            this->m_fds[i].fd = m_channel->getSocket();
            this->m_fds[i].events = events;
            this->m_maxfd = (i > this->m_maxfd) ? i : this->m_maxfd;
            break;
        }
    }

    // 什么时候用poll elect 检测的fd不多 ，大多数是激活的 qq在聊天是激活  qq挂起不激活
    if (i >= this->m_maxNode)
    {
        return -1;
    }
    // 添加到poll中

    return 0;
}
// 移除 ,把一个节点从epoll树上删除
int PollDispatcher::remove()
{
    int i = 0;
    for (; i < this->m_maxNode; i++)
    {
        if (this->m_fds[i].fd == m_channel->getSocket())
        {
            // 说明找到一个空闲的位置
            this->m_fds[i].fd = -1;
            this->m_fds[i].events = 0;
            this->m_fds[i].revents = 0;
            break;
        }
    }
    // 通过channel释放对应的TcpConnection 的资源
    channel->destoryCallBack(const_cast<void*>(m_channel->getArg()));
    if (i >= this->m_maxNode)
    {
        return -1;
    }

    // 什么时候用poll elect 检测的fd不多 ，大多数是激活的 qq在聊天是激活  qq挂起不激活

    return 0;
}

// 修改把一个节点从epoll树上修改
int PollDispatcher::modify()
{
    
    // 设置事件events
    int events = 0;
    if (this->m_channel->getEvent() & static_cast<int>(FDEvent::ReadEvent))
    {
        events |= POLLIN;
    }
    // 不能同时判断读或者写
    if (this->m_channel->getEvent() & static_cast<int>(FDEvent::WriteEvent))
    {
        events |= POLLOUT;
    }
    // 遍历找到一个空闲饿、位置放进去

    int i = 0;
    for (; i < this->m_maxNode; i++)
    {
        if (this->m_fds[i].fd == this->m_channel->getSocket())
        {
            // 说明找到一个空闲的位置
            this->m_fds[i].events = events;
            break;
        }
    }

    // 什么时候用poll elect 检测的fd不多 ，大多数是激活的 qq在聊天是激活  qq挂起不激活

    return 0;
}
// 事件检测 ，检测epoll树上是否有事件发生
int PollDispatcher::PollDispatcher::dispatch(int timeout = 2) // 单位秒
{
    int count = poll(this->m_fds, this->m_maxfd+1, timeout * 1000); // 传进来的事件是ms

    if (count == -1)
    {
        perror("poll error");
    }

    // 这个count 只是表示多少个事件就绪了 ，并不能表示这写文件描述符是连续得
    for (int i = 0; i <=  this->m_maxfd; i++)
    {
        // 判断返回来得事件是什么

        if (this->m_fds[i].fd == -1)
        {
            continue;
        }

        // if (data->fds[i].revents & POLLERR || data->fds[i].revents & POLLHUP)
        // {
        //     // 错误事件
        //     // 关闭文件描述符
        // }
        if (dthis->m_fds[i].revents & POLLIN)
        {
            // 读事件
            eventActivate(eventLoop, data->fds[i].fd, ReadEvent);
        }
        if (data->fds[i].revents & POLLOUT)
        {
            eventActivate(eventLoop, data->fds[i].fd, WriteEvent);
            // 写事件
        }
    }
    return 0;
}

PollDispatcher::~PollDispatcher()
{
    delete[] this->m_fds;
}









